package objects;

import interfaces.ActionInterface;


import interfaces.AgentInterface;
import interfaces.impl.HumanInteraction;

import java.awt.Graphics;
import java.util.ArrayList;
import java.util.PriorityQueue;



import universe.Universe;

import extra.Position;

import constants.*;




public class WorldObject implements Comparable<WorldObject> {

	private Position position; //that refers to the mid position, where there are collision with the terrain
	private int type;
	private int ID;
	
	private ImageObject imageObject;
	private int objectReference; //its His ID  but now i used to refers images
	
	private ArrayList<WorldObject> listObjects;
	private ArrayList<WorldObject> listFather;
	
	
	private PriorityQueue<ActionInterface> normalActions;    //i put here the normal actions whose has a normal time to execute
	private PriorityQueue<ActionInterface> immediatlyActions;//i put here actions that occurs immediatly like walk or drink potions 
	
	private ArrayList<ActionInterface> listActions;
	private ArrayList<SpetialFeature>  listFeatures;
	private ArrayList<AgentInterface>  listAgents;
	
	private ArrayList<HumanInteraction> listHumanInteractions;
	
	private ArrayList<AgentInterface> listAgentsToRemove;
	
	private double actionWaitTime=0;
	private boolean executing=false;
	
	private boolean visible = true;
	private boolean isActive = true;
	
		
	public WorldObject(){
		
		position=new Position();
		objectReference= Constants.OBJECT_REFERENCE_BOMBERMAN;
		imageObject=new ImageObject();//.createImageObject(Constants.OBJECT_REFERENCE_BOMBERMAN);
		setObjectReference(objectReference);
		
		listFeatures= new ArrayList<SpetialFeature>();
		listAgents = new ArrayList<AgentInterface>();
		listActions= new ArrayList<ActionInterface>();
		
		normalActions= new PriorityQueue<ActionInterface>();
		immediatlyActions=new PriorityQueue<ActionInterface>();
		
		listHumanInteractions= new ArrayList<HumanInteraction>();
		listObjects = new ArrayList<WorldObject>();
		
		listAgentsToRemove= new ArrayList<AgentInterface>();
		listFather = new ArrayList<WorldObject>();
	}
	
	public WorldObject(WorldObject object){
		
		position= new Position(object.position);
		this.type=object.type;
		
		this.objectReference=object.objectReference;
		setObjectReference(objectReference);
		
		this.imageObject= new ImageObject(object.getImageObject());
		
		listFeatures= new ArrayList<SpetialFeature>();
		listAgents = new ArrayList<AgentInterface>();
		
		this.listAgents= (ArrayList<AgentInterface>) object.listAgents.clone();
		this.listFeatures = (ArrayList<SpetialFeature>) object.listFeatures.clone();
		this.listActions = (ArrayList<ActionInterface>) object.listActions.clone();
		this.listHumanInteractions = (ArrayList<HumanInteraction>) object.listHumanInteractions.clone();
		this.listObjects = (ArrayList<WorldObject>) object.listObjects.clone();
		this.listFather= (ArrayList<WorldObject>) object.listFather.clone();
		
		normalActions= new PriorityQueue<ActionInterface>();
		immediatlyActions=new PriorityQueue<ActionInterface>();
		
		listAgentsToRemove = new ArrayList<AgentInterface>();
		
	}

	public int getType() {
		return type;
	}


	public void setType(int type) {
		this.type = type;
	}

	public void paint(Graphics g) {
		
		imageObject.paint(g);
		
	}

	/*public void paintCollitionShape(Graphics g){
		g.setColor(Color.black);
		g.drawRect(x+xRadio,y+yRadio,radioWidth,radioHeight);
		g.fillRect(x+xRadio,y+yRadio,radioWidth,radioHeight);
		
	}*/
		
	@Override
	public int compareTo(WorldObject object) {
		if(position.getY()<object.position.getY()){
			
			return -1;
		}
		if(position.getY()>object.position.getY()){
			return 1;
		}
		return 0;

	}

	public int getObjectReference() {
		return objectReference;
	}
 
	public void setObjectReference(int objectReference) {
		this.objectReference = objectReference;
	}
	
	public void addSpetialFeature(SpetialFeature feature) {
		listFeatures.add(new SpetialFeature(feature));
	}

	public void addAgent(AgentInterface agent){
		listAgents.add(agent);
	}
	
	public void print() {
		for(SpetialFeature feat : listFeatures){
			System.out.println(feat.getName()+" value: "+feat.getValue());
		}
		
	}

	public ArrayList<SpetialFeature> getListFeatures() {
		return listFeatures;
	}

	public void setListFeatures(ArrayList<SpetialFeature> listFeatures) {
		this.listFeatures = listFeatures;
	}

	public ArrayList<AgentInterface> getListAgents() {
		return listAgents;
	}

	public void setListAgents(ArrayList<AgentInterface> listAgents) {
		this.listAgents = listAgents;
	}

	public String save(String save) {
		
		save=save +factory.Constants.OBJECT_WORLD_ID+","+position.getX()+","+position.getY()+","+objectReference;

		for(AgentInterface ag : listAgents ){
			save=save+","+ag.getID();
		}
		
		if(!listFeatures.isEmpty()){
		save = save +",SPETIAL";
			for(SpetialFeature fe : listFeatures){
				//save Features
				save=save+","+fe.save();
			}
		}
		
		if(!listActions.isEmpty()){
			save = save +",ACTIONS";
				for(ActionInterface ac : listActions){
					//save Features
					save=save+","+ac.getId();
				}
			}
		
		
		save=save+System.getProperty("line.separator");
				
		
		return save;
	}
	
	public WorldObject load(String[] linesElements, int i) {
		
		double x,y;
		
		x=Float.parseFloat(linesElements[i]);
		i++;
		y=Float.parseFloat(linesElements[i]);
		i++;
		WorldObject obj = new WorldObject();//ObjectFactory.createWorldObject(Integer.parseInt(linesElements[i]));
		obj.setObjectReference(Integer.parseInt(linesElements[i]));
		obj.position=new Position(x,y);
		
		return obj;
		/*WorldObject obj = new WorldObject();
		obj.position.setX((Float.parseFloat(linesElements[i])));
		i++;
		obj.position.setY(Float.parseFloat(linesElements[i]));
		i++;
		obj.setObjectReference(Integer.parseInt(linesElements[i]));
		
		i++;
		//Load Agents
		for(int j=i;j<linesElements.length;j++){
			if(linesElements[j].equals("SPETIAL")){
				i=j;
				break; 
			}
			else{
				System.out.println("Estoy pegando Agentes "+Integer.parseInt(linesElements[j]));
				AgentSingleton.setAgent(obj, Integer.parseInt(linesElements[j]));
				
				
			}
		}
		//load SpetialFeatures
		if(i<linesElements.length){
			if(linesElements[i].equals("SPETIAL")){
				i++;
				SpetialFeature feature = new SpetialFeature();
				for(int j=i;j<linesElements.length;j++){
					if(linesElements[j].equals("ACTIONS")){
						i=j;
						break;
					}
					feature.setId(Integer.parseInt(linesElements[j]));
					j++;
					feature.setName(linesElements[j]);
					j++;
					feature.setValue(Double.parseDouble(linesElements[j]));
					obj.addSpetialFeature(feature);
				}
			}
			if(linesElements[i].equals("ACTIONS")){
				i++;
				for(int j=i;j<linesElements.length;j++){
					obj.addAction(ActionFactory.getAction(Integer.parseInt(linesElements[j])));
					System.out.println("Cargo Action "+Integer.parseInt(linesElements[j]));
				}
			}
		}
		
		return obj;*/
	}
	
	public boolean containsAgent(int id){
		for(AgentInterface ag : listAgents){
			if (ag.getID()==id){
				return true;
			}
		}
		return false;
	}

	public void removeAgent(int agentReference) {
		for(AgentInterface ag : listAgents){
			if(ag.getID()==agentReference){
				listAgents.remove(ag);
				return;
			}
		}
		
	}
	public boolean containsSpetialFeature(int id){
		for(SpetialFeature fe : listFeatures){
			if (fe.getId()==id){
				return true;
			}
		}
		return false;
	}

	public void removeSpetialFeature(int featureReference) {
		for(SpetialFeature fe : listFeatures){
			if (fe.getId()==featureReference){
				listFeatures.remove(fe);
				return;
			}
		}
		
	}

	public Position getPosition() {
		return position;
	}

	public void setPosition(Position position) {
		this.position = position;
		int x = (int)(position.getX()-imageObject.getImageToShow().getWidth()/2);
		int y = (int)(position.getY()-imageObject.getImageToShow().getHeight()/2);
		imageObject.setPosition(new Position(x,y));
		
	}

	public ImageObject getImageObject() {
		return imageObject;
	}

	public void setImageObject(ImageObject imageObject) {
		this.imageObject = imageObject;
	}

	public ArrayList<ActionInterface> getListActions() {
		return listActions;
	}

	public void setListActions(ArrayList<ActionInterface> listActions) {
		this.listActions = listActions;
	}
	
	

	public void setNormalActionToDo(ActionInterface action) {
		
		if(!normalActions.contains(action)){
			normalActions.add(action);
		}
		else{
			System.out.println("ya tengo la accion");
		}
		//System.out.println("Size queue "+normalActions.size());
	}
	
	public void setImmediatlyActionToDo(ActionInterface action){

		for(ActionInterface ac : immediatlyActions){
			if(ac.getId()==action.getId() && !immediatlyActions.contains(ac)){
				return;
				
			}
		}
		

		immediatlyActions.add(action);
//			System.out.println("Pego la accion "+action.getName()+" empty "+immediatlyActions.isEmpty());

		
		
	}
	
	public void addAction(ActionInterface action){
		listActions.add(action);
		
	}
	
	
	
	
	
	
	public boolean processNormalActions(double time, Universe world ){
		
		if(normalActions.isEmpty()){
			actionWaitTime=0;
			return false;
		}
		actionWaitTime=actionWaitTime+time;
		
		if(!executing){
			if(actionWaitTime>normalActions.peek().getWaitTimeToExecute()){
				executing=normalActions.peek().processAction(world);
				System.out.println("proceso accion");
				if(executing==false){
					System.out.println("No pude realizar la accion");
					normalActions.poll();
					actionWaitTime=0;
				}

			}
		}
		else{
			if(actionWaitTime>normalActions.peek().getExecuteTime()){
				System.out.println("SAcO de la cola");
				normalActions.poll();
				executing=false;
				actionWaitTime=0;
			}
		}
		return true;
	}
	
	public void processImmediatlyActions(double time,Universe world){
		//System.out.println("ptoceso cola "+immediatlyActions.isEmpty());
		while(!immediatlyActions.isEmpty()){
			ActionInterface action = immediatlyActions.poll();
			//System.out.println("proceso la accion: "+action.getName());
			action.processAction(world);
			//System.out.println("vacio la cola "+immediatlyActions.size());
		}
		//System.out.println("ya no hay nada "+immediatlyActions.isEmpty());
		
	}

	public void addHumanInteraction(HumanInteraction humanInteraction) {
		
			listHumanInteractions.add(humanInteraction);
			listAgents.add(humanInteraction);
		
	}

	public ArrayList<HumanInteraction> getListHumanInteractions() {
		return listHumanInteractions;
	}

	public void setListHumanInteractions(ArrayList<HumanInteraction> listHumanInteractions) {
		this.listHumanInteractions = listHumanInteractions;
	}

	public ArrayList<WorldObject> getListObjects() {
		return listObjects;
	}

	public void addObject(WorldObject object) {
		listObjects.add(object);
		object.addFather(this);
	}

	private void addFather(WorldObject object) {
			this.listFather.add(object);
	}

	public boolean isVisible() {
		return visible;
	}

	public void setVisible(boolean visible) {
		this.visible = visible;
	}

	public boolean isActive() {
		// TODO Auto-generated method stub
		return isActive ;
	}

	public boolean isExecuting() {
		return executing;
	}

	public void setExecuting(boolean executing) {
		this.executing = executing;
	}

	public void setActive(boolean isActive) {
		this.isActive = isActive;
	}
	
	public void addAgentToRemove(AgentInterface ag){
		listAgentsToRemove.add(ag);
	}
	
	public void processAgentsToRemove() {
		for(AgentInterface ag : listAgentsToRemove){
			listAgents.remove(ag);
		}
		listAgentsToRemove.clear();
	}

	public ArrayList<WorldObject> getListFather() {
		return listFather;
	}

	public void setListFather(ArrayList<WorldObject> listFather) {
		this.listFather = listFather;
	}

	
	public String messageUpdateObject(){
		String result = new String();
			result=+objectReference+";"+imageObject.getPosition().getX()+";"+imageObject.getPosition().getY()+";"+isActive+";"+ID;
		
		
		return result;
	}
	
	public static String messageAskForAgentsFromObject(int x, int y){
		String msg = new String();
		msg=Message.ASK_FOR_ACTION_FROM_OBJECT+System.lineSeparator()+x+";"+y;
		return msg;
	}

	public static WorldObject createObject(String str) {
		
		WorldObject obj = new WorldObject();
		
		String splt[]=str.split(";");
		obj.objectReference=Integer.parseInt(splt[0]);
		obj.imageObject.getPosition().setX(Double.parseDouble(splt[1]));
		obj.imageObject.getPosition().setY(Double.parseDouble(splt[2]));
		obj.isActive=Boolean.parseBoolean(splt[3]);
		obj.ID=Integer.parseInt(splt[4]);
		
		return obj;
	}

	public static Position getPositionFromMessageAskForActionFromObject(String str) {
		Position p= new Position();
		String r[]=str.split(";");
		p.setX(Double.parseDouble(r[0]));
		p.setY(Double.parseDouble(r[1]));
		
		return p;
	}

	public String messageAgentsFromObject() {
		String msg = new String();
		for(AgentInterface ag : listHumanInteractions){
			msg=msg+ag.getName()+System.lineSeparator();
		}
		return msg;
	}

	public int getID() {
		// TODO Auto-generated method stub
		return ID;
	}

	public void setID(int id) {
		this.ID=id;
		
	}

	
}
